#include "form_setting_log.h"
#include "ui_form_setting_log.h"

// add nacessary includes here
#include "utils/database/database_bll_t1c.h"
#include "utils/can/can_bll_t1c.h"
#include "ui/share/form_shield_dlg.h"
#include "ui/share/form_prompt_dlg.h"

#define DF_TBL_ROW_CNT_LIMIT        20
#define DF_VALID_COLUMNS            4

static int g_nPageIdx = 0;

/*
 * Function:    FormSettingLog
 * Description: The default constructor
 * Paramer:     void
 * Return:
 */
FormSettingLog::FormSettingLog(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FormSettingLog)
{
    qDebug() << Q_FUNC_INFO;

    ui->setupUi(this);
}

/*
 * FormHistoryResult:    ~FormSettingLog
 * Description: The default destructor
 * Paramer:     void
 * Return:
 */
FormSettingLog::~FormSettingLog()
{
    qDebug() << Q_FUNC_INFO;

    delete ui;
}

/*
 * Function:    getInstance
 * Description: Get an instance of "FormSettingLog" class, if exist, return it
 * Paramer:     QWidget *pParent - the pointer of QWidget class
 * Return:      the pointer of "FormSettingLog" class
 */
FormSettingLog* FormSettingLog::getInstance(QWidget *pParent)
{
    static FormSettingLog *pNew = NULL;
    if(!pNew) {
        qDebug() << Q_FUNC_INFO;

        // Create a new object if it doesn't exist
        pNew = new FormSettingLog(pParent);
        if(NULL == pNew) return NULL;

        // After constructing object, initialize the object
        pNew->_initialze();

        // Initialize control's UI
        pNew->_initUi();

        // Hide widget firstly
        pNew->hide();
    }
    else {
        // Set the parent object
        pNew->setParent(pParent);
    }

    return pNew;
}

/*
 * Function:    _initialze
 * Description: After constructing object, initialize the object
 * Paramer:     void
 * Return:      void
 */
void FormSettingLog::_initialze()
{
    qDebug() << Q_FUNC_INFO;

    Q_ASSERT(DatabaseBLL_T1C::getInstance(this));

    // Signal-slot initialization
    std::vector<bool> vecConnect;

    vecConnect.push_back(QObject::connect(this, SIGNAL(signalRefreshUI()), this, SLOT(slotRefreshUI()), static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection)));
    vecConnect.push_back(QObject::connect(CanBLL_T1C::getInstance(this), SIGNAL(signalErrorLogPayload(unsigned int, int, int)), this, SLOT(slotErrorLogPayload(unsigned int, int, int)), static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection)));

    for(int i=0; i<(int)vecConnect.size(); i++) {
        Q_ASSERT(vecConnect.at(i));
    }
}

/*
* Function:		_initUi
* Description:	Init the window style
* Paramer:		void
* Return:		void
*/
void FormSettingLog::_initUi()
{
    qDebug() << Q_FUNC_INFO;

    // Displays the background image of the window
    QWidget::setAttribute(Qt::WA_StyledBackground);

    SET_STYLE_SHEET(QString(":/%1/setting/%2.qss").arg("skin_1").arg(this->objectName()));

    ui->label_Page->setText("");

    if(!m_pModelItem) m_pModelItem = new QStandardItemModel();
    m_pModelItem->setHorizontalHeaderItem(E_EIF_ERR_ID, new QStandardItem("error_id"));
    m_pModelItem->setHorizontalHeaderItem(E_EIF_ERR_TIME, new QStandardItem(QObject::tr("Time")));
    m_pModelItem->setHorizontalHeaderItem(E_EIF_ERR_LEVEL, new QStandardItem(QObject::tr("Level")));
    m_pModelItem->setHorizontalHeaderItem(E_EIF_ERR_CODE, new QStandardItem(QObject::tr("Coding")));
    m_pModelItem->setHorizontalHeaderItem(E_EIF_ERR_CHANNEL, new QStandardItem(QObject::tr("Channel")));
    m_pModelItem->setHorizontalHeaderItem(E_EIF_ERR_SCENE, new QStandardItem(QObject::tr("Discription")));

    ui->tableView_LogList->setModel(m_pModelItem);
    ui->tableView_LogList->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->tableView_LogList->resizeRowsToContents();
    ui->tableView_LogList->horizontalHeader()->setFixedHeight(30);
    ui->tableView_LogList->horizontalHeader()->setStretchLastSection(true);
    ui->tableView_LogList->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    ui->tableView_LogList->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    ui->tableView_LogList->verticalHeader()->setMinimumSectionSize(65);
    ui->tableView_LogList->setSelectionBehavior (QAbstractItemView::SelectRows);
    ui->tableView_LogList->setSelectionMode (QAbstractItemView::SingleSelection);
    ui->tableView_LogList->setAlternatingRowColors(true);
    ui->tableView_LogList->setColumnHidden(E_EIF_ERR_ID, true);
    ui->tableView_LogList->setColumnHidden(E_EIF_ERR_CHANNEL, true);
    ui->tableView_LogList->setColumnWidth(E_EIF_ERR_TIME, 200);
    ui->tableView_LogList->setColumnWidth(E_EIF_ERR_LEVEL, 200);
    ui->tableView_LogList->setColumnWidth(E_EIF_ERR_CODE, 200);
    ui->tableView_LogList->setColumnWidth(E_EIF_ERR_SCENE, 200);
}

/*
* Function:		slotRefreshUI
* Description:	The slot that refresh UI info
* Paramer:		void
* Return:		void
*/
void FormSettingLog::slotRefreshUI()
{
    qDebug() << Q_FUNC_INFO;

    int nRecordCnt = 0;
    int nListCnt = 0;
    _displayLogListByPaging(nRecordCnt, nListCnt, DF_TBL_ROW_CNT_LIMIT, g_nPageIdx);

    QString sPageInfo = QString("%1/%2").arg(g_nPageIdx / DF_TBL_ROW_CNT_LIMIT + 1).arg(nRecordCnt / DF_TBL_ROW_CNT_LIMIT + 1);
    ui->label_Page->setText(sPageInfo);
}

/*
* Function:	slotRefreshUI
* Description:	Receive a payload data from serialport (error log)
* Paramer:	unsigned int unCanId - CAN ID
*               int nLevel - error level
*               int nCoding - error coding
* Return:	void
*/
void FormSettingLog::slotErrorLogPayload(unsigned int unCanId, int nLevel, int nCoding)
{
    qDebug() << Q_FUNC_INFO << unCanId << nLevel << nCoding;

    int nChannelNumber = 0;

    if(CanVars::gs_nIapCanID_CH1 == (unCanId - 1)) { nChannelNumber = 1; }
    else if(CanVars::gs_nIapCanID_CH2 == (unCanId - 1)) { nChannelNumber = 2; }
    else if(CanVars::gs_nIapCanID_CH3 == (unCanId - 1)) { nChannelNumber = 3; }
    else if(CanVars::gs_nIapCanID_CH4 == (unCanId - 1)) { nChannelNumber = 4; }
    else return;

    // Save the error info
    ST_ERROR_INFO stErrorInfo;
    stErrorInfo.nChannel = nChannelNumber;
    stErrorInfo.nErrLevel = nLevel;
    stErrorInfo.lErrCode = nCoding;
    stErrorInfo.nChannel = 1;
    stErrorInfo.sErrScene = UtilityAPI::getInstance()->getErrorDescByCodeInspect(nCoding);
    stErrorInfo.sCreateTime = DEF_CUR_TIME_EX;

    int nRetVal = DatabaseBLL_T1C::getInstance(this)->saveErrorInfo(stErrorInfo);
    if(0 == nRetVal) {
        // Display error info on status
        emit signalDisplayErrorInfoOnStatus(stErrorInfo.nErrLevel, stErrorInfo.sErrScene);
    }
}

/*
* Function:		changeEvent
* Description:	Triggers an event before it is switch language
* Paramer:		QShowEvent *event - the pointer of "QEvent"
* Return:		void
*/
void FormSettingLog::changeEvent(QEvent *e)
{
    switch (e->type()) {
    case QEvent::LanguageChange:
    {
        QStringList lstHeader = QStringList() << "error_id" << tr("Time") << tr("Level") << tr("Coding") << tr("Channel") << tr("Discription");
        m_pModelItem->setHorizontalHeaderLabels(lstHeader);

        ui->retranslateUi(this);
        qDebug() << Q_FUNC_INFO;
        break;
    }
    default:
        break;
    }

    QWidget::changeEvent(e);
}

void FormSettingLog::on_pushButton_LastPage_clicked()
{
    qDebug() << Q_FUNC_INFO << g_nPageIdx;

    g_nPageIdx -= DF_TBL_ROW_CNT_LIMIT;
    if(0 >= g_nPageIdx) g_nPageIdx = 0;

    // Display the chip data list by paging
    int nRecordCnt = 0;
    int nListCnt = 0;
    _displayLogListByPaging(nRecordCnt, nListCnt, DF_TBL_ROW_CNT_LIMIT, g_nPageIdx);

    QString sPageInfo = QString("%1/%2").arg(g_nPageIdx / DF_TBL_ROW_CNT_LIMIT + 1).arg(nRecordCnt / DF_TBL_ROW_CNT_LIMIT + 1);
    ui->label_Page->setText(sPageInfo);
}

void FormSettingLog::on_pushButton_NextPage_clicked()
{
    qDebug() << Q_FUNC_INFO << g_nPageIdx;

    g_nPageIdx += DF_TBL_ROW_CNT_LIMIT;

    // Display the chip data list by paging
    int nRecordCnt = 0;
    int nListCnt = 0;
    _displayLogListByPaging(nRecordCnt, nListCnt, DF_TBL_ROW_CNT_LIMIT, g_nPageIdx);
    if(0 == nListCnt) {
        g_nPageIdx -= DF_TBL_ROW_CNT_LIMIT;
        if(0 > g_nPageIdx) g_nPageIdx = 0;
    }

    QString sPageInfo = QString("%1/%2").arg(g_nPageIdx / DF_TBL_ROW_CNT_LIMIT + 1).arg(nRecordCnt / DF_TBL_ROW_CNT_LIMIT + 1);
    ui->label_Page->setText(sPageInfo);
}

/*
* Function:		_displayLogListByPaging
* Description:	Display the log data list by paging
* Paramer:		int nRecordCnt - the records count
*               int nLimit - the record rows
*               int nOffset - the start index of the rows
* Return:		int - the error code
*/
int FormSettingLog::_displayLogListByPaging(int & nRecordCnt, int & nListCnt, int nLimit, int nOffset)
{
    qDebug() << Q_FUNC_INFO << nLimit << nOffset;

    int nRetVal = 0;
    QList<ST_ERROR_INFO> lstErrLog;

    // Get the log list
    DatabaseBLL_T1C::getInstance(this)->getErrListByFilter(lstErrLog, nRecordCnt, nLimit, nOffset);
    if(0 == nRetVal) {
        int nRowCnt = lstErrLog.size();
        if(0 < nRowCnt) {
            // Clear all rows
            m_pModelItem->removeRows(0, m_pModelItem->rowCount());

            for(int i=0; i<nRowCnt; i++) {
                QString sErrId = QString::number(lstErrLog.at(i).nErrId);
                QString sErrCode = QString::number(lstErrLog.at(i).lErrCode);;
                QString sErrLevel = UtilityAPI::getInstance()->getErrorLevelByType(lstErrLog.at(i).nErrLevel);
                QString sErrDesc = UtilityAPI::getInstance()->getErrorDescByCodeInspect(lstErrLog.at(i).lErrCode);
                QString sDatetime = QDateTime::fromString(lstErrLog.at(i).sCreateTime, "yyyy-MM-dd hh:mm:ss.zzz").toString("yyyy-MM-dd hh:mm:ss");

                m_pModelItem->setItem(i, E_EIF_ERR_ID, new QStandardItem(sErrId));
                m_pModelItem->setItem(i, E_EIF_ERR_TIME, new QStandardItem(sDatetime));
                m_pModelItem->setItem(i, E_EIF_ERR_LEVEL, new QStandardItem(sErrLevel));
                m_pModelItem->setItem(i, E_EIF_ERR_CODE, new QStandardItem(sErrCode));
                m_pModelItem->setItem(i, E_EIF_ERR_SCENE, new QStandardItem(sErrDesc));

                m_pModelItem->item(i, E_EIF_ERR_TIME)->setTextAlignment(Qt::AlignCenter);
                m_pModelItem->item(i, E_EIF_ERR_LEVEL)->setTextAlignment(Qt::AlignCenter);
                m_pModelItem->item(i, E_EIF_ERR_CODE)->setTextAlignment(Qt::AlignCenter);
                m_pModelItem->item(i, E_EIF_ERR_SCENE)->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
            }

            ui->tableView_LogList->resizeRowsToContents();
        }
    }

    nListCnt = lstErrLog.size();

    // Get the log list
    qDebug() << Q_FUNC_INFO << nRetVal << nRecordCnt << nListCnt;
    return nRetVal;
}
